package com.NeuglsWorkStudio.UI.FormElement.Component.Video
{
	import com.NeuglsWorkStudio.UI.FormElement.Component.TComponent;
	import com.NeuglsWorkStudio.UI.FormElement.Config.TConfig;
	import com.NeuglsWorkStudio.UI.FormElement.Config.TVideoControlBarConfig;
	import com.NeuglsWorkStudio.UI.FormElement.Config.TVideoPlayerConfig;
	import com.NeuglsWorkStudio.UI.FormElement.Config.TVideoPreviewConfig;
	import com.NeuglsWorkStudio.UI.FormElement.Interfaces.IMediaControl;
	import com.NeuglsWorkStudio.UI.FormElement.Interfaces.MediaStatusType;
	import com.NeuglsWorkStudio.Utility.Resource.ResourceLoader;
	import com.NeuglsWorkStudio.Utility.Resource.ResourceLoaderOption;
	import com.NeuglsWorkStudio.Utility.TFunctionManager;
	
	import flash.display.Sprite;
	import flash.display.StageDisplayState;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.NetStatusEvent;
	import flash.events.SecurityErrorEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.media.SoundTransform;
	import flash.media.Video;
	import flash.net.NetConnection;
	import flash.net.NetStream;
	import flash.net.NetStreamPlayOptions;
	
	
	public class TVideoPlayer extends TComponent implements IMediaControl
	{
		private var _FVideo:Video;
		private var _FPreviewPicture:TVideoPreview;
		private var _FVideoContainer:Sprite;
		private var _FVideoControlBar:TVideoControlBar;
		private var _FNetStream:NetStream;
		private var _FConnect:NetConnection;
		
		private var _FDoPlayed:Boolean=false;
		private var _FStatus:int=0;
		
		private var _FVideoOriganWidth:Number=0;
		private var _FVideoOriganHeight:Number=0;
		private var _FVideoDuration:Number=0;
		
		private var _FPlayFunctionManager:TFunctionManager;
		private var _FVideoHeight:Number=0;
		
		private var _FT:String;
		
		public function TVideoPlayer(AConfig:TConfig)
		{
			super(AConfig);
		}
		
		public function VideoPlayerConfig():TVideoPlayerConfig{
			return _FConfig as TVideoPlayerConfig
		}
		
		override protected function Init():void{
			super.Init();
			_FT=new Date().toLocaleTimeString();
			_FPlayFunctionManager=new TFunctionManager();
			
			_FVideoContainer=new Sprite();
			_FVideoContainer.buttonMode=true;
			
			var ControlBarConfig:TVideoControlBarConfig=new TVideoControlBarConfig();
			//ControlBarConfig.BaseColor=this.VideoPlayerConfig().BaseColor;
			ControlBarConfig.BaseColor=0xFFFFFF;
			ControlBarConfig.MediaControlInterface=this;
			ControlBarConfig.Name='videoplayercontrolbar';
			ControlBarConfig.Width=VideoPlayerConfig().Width;
			ControlBarConfig.x=0;
			ControlBarConfig.y=VideoPlayerConfig().Height-20;
			ControlBarConfig.OnFullScreen=this.OnFullScreen;
			_FVideoControlBar=new TVideoControlBar(ControlBarConfig);
			this.addChild(_FVideoContainer);
			this.addChild(_FVideoControlBar);
			_FVideoControlBar.y=VideoPlayerConfig().Height-_FVideoControlBar.height;
			_FVideoHeight=_FVideoControlBar.y;
			
			//load preview picture
			if(!VideoPlayerConfig().AutoPlay){
				var PreviewConfig:TVideoPreviewConfig=new TVideoPreviewConfig();
				PreviewConfig.BaseColor=VideoPlayerConfig().BaseColor;
				PreviewConfig.Height=_FVideoHeight;
				PreviewConfig.Image=null;
				PreviewConfig.ImageURL=VideoPlayerConfig().VideoPicURL;
				PreviewConfig.Name='PreviewPicture';
				PreviewConfig.OnPlayBtnClick=function():void{Play()};
				PreviewConfig.UserURL=true;
				PreviewConfig.Width=VideoPlayerConfig().Width;
				PreviewConfig.x=0;
				PreviewConfig.y=0;
				
				_FPreviewPicture=new TVideoPreview(PreviewConfig);
				_FVideoContainer.addChild(_FPreviewPicture);
			}
			
			_FVideoContainer.addEventListener(MouseEvent.CLICK,function(E:MouseEvent):void{
				Toggle();
			});
			
			InitVideo();
			if(VideoPlayerConfig().AutoPlay){
				DoPlay();
			}
		}
		
		
		private var _FOldInfo:Object={};//Used to store the old video player info.
		private function OnFullScreen():void{
			if(this.stage){
				/*var PTopLeft:Point=this.localToGlobal(new Point(0,0));
				var PBottomRight:Point=this.localToGlobal(new Point(this.width,this.height));
				
				var screenRectangle:Rectangle=new Rectangle();
				screenRectangle.topLeft=PTopLeft;
				screenRectangle.bottomRight=PBottomRight;
				
				this.stage.fullScreenSourceRect = screenRectangle;
				this.stage.displayState = StageDisplayState.FULL_SCREEN;*/
				
				_FOldInfo.Parent=this.parent;
				_FOldInfo.x=this.x;
				_FOldInfo.y=this.y;
				
				this.stage.addChild(this);			
				this.addEventListener(Event.ADDED_TO_STAGE,OnFullScreenAddToStage);
			}
			
			
		}
		
		private function OnFullScreenAddToStage(E:Event):void{
			this.removeEventListener(Event.ADDED_TO_STAGE,OnFullScreenAddToStage);
			this.x=0;
			this.y=0;
			this.VideoPlayerConfig().Width=stage.stageWidth;
			this.VideoPlayerConfig().Height=stage.stageHeight;
		}
		
		private function InitVideo():void{
			//Create connection
			_FConnect=new NetConnection();
			_FConnect.addEventListener(NetStatusEvent.NET_STATUS,NetStatusHandler);
			_FConnect.addEventListener(SecurityErrorEvent.SECURITY_ERROR,SecurityErrorHandler);
			_FConnect.connect(null);
		}
		
		private function ConnectStream():void{
			//Create net stream
			_FNetStream=new NetStream(_FConnect);
			_FNetStream.addEventListener(NetStatusEvent.NET_STATUS,NetStatusHandler);
			
			_FNetStream.client={
				onMetaData:OnGetMetaData,
				onImageData:OnReceiveImage,
				onPlayStatus:OnPlayStatusChanged,
				onTextData:OnReceiveTextData
			};
			_FVideo=new Video(VideoPlayerConfig().Width,_FVideoHeight);
			_FVideo.attachNetStream(_FNetStream);
			
			trace('Video attached stream*****************'+_FT);
		}
		
		private function DoPlay():Boolean{
			if(_FDoPlayed) return _FDoPlayed;
			_FNetStream.play(VideoPlayerConfig().VideoURL);
			_FVideoContainer.addChild(_FVideo);
			
			_FDoPlayed=true;
			_FStatus=MediaStatusType.Playing;
			
			_FVideoControlBar.UpdateInfo();
			_FPlayFunctionManager.doFunction('OnPlay');
			trace('Video Do play*****************'+_FT);
			return false;
		}
		
		private function OnGetMetaData(MetaData:Object):void{
			_FVideoOriganWidth=MetaData.width;
			_FVideoOriganHeight=MetaData.height;
			_FVideoDuration=MetaData.duration;
			trace('Get meta data, duration: '+MetaData.duration);
		}
		
		private function OnReceiveImage(ImageData:Object):void{
			/*trace("imageData length: " + imageData.data.length);
			var imageloader:Loader = new Loader();           
			imageloader.loadBytes(imageData.data); // imageData.data is a ByteArray object.
			addChild(imageloader);*/
		}
		
		
		private function OnReceiveTextData(TextData:Object):void{
			/*trace("--- textData properties ----");
                var key:String;

                for (key in textData) {
                    trace(key + ": " + textData[key]);
                }*/
		}
		
		private function OnPlayStatusChanged(StatusData:Object):void{
			trace(StatusData.code);
			/*if(dat.code == "NetStream.Play.Complete") {  
				forward(dat,'complete');  
			} else {  
				forward(dat,'playstatus');  
			}  */
			switch(StatusData.code){
				case "NetStream.Play.Switch":
					break;
				case "NetStream.Play.Complete":
										
					break;
				case "NetStream.Play.TransitionComplete":
					break;
			}
		}
		
		/**
		 * 播放器播放完毕*/
		private function OnComplete():void{
			switch(VideoPlayerConfig().Loop){
				case -1:
					_FNetStream.seek(0);
					Play();
					break;
				case 0:
					this.Stop();
					break;
				default:
					VideoPlayerConfig().Loop--;
					if(VideoPlayerConfig().Loop>0){
						_FNetStream.seek(0);
						Play();
					}else{
						this.Stop();
					}
			}
		}
		
		private function DispatchEvent(EventType:String,ErrorCode:uint=0,ErrorMsg:String=''):void{
			var VideoEvent:TVideoEvent=new TVideoEvent(EventType);
			VideoEvent.ErrorCode=ErrorCode;
			VideoEvent.ErrorMsg=ErrorMsg;
			dispatchEvent(VideoEvent);
		}
		
		private function NetStatusHandler(E:NetStatusEvent):void{
			trace(E.info.code+'**************'+_FT);
			switch (E.info.code) {
				case "NetConnection.Connect.Success":
					ConnectStream();
					break;
				case "NetStream.Play.StreamNotFound":
					DispatchEvent(TVideoEvent.VIDEO_ERROR,TVideoEvent.ecStreamNotFound,VideoPlayerConfig().VideoURL);
					break;
				case "NetStream.Pause.Notify":
					DispatchEvent(TVideoEvent.VIDEO_PAUSED);
					break;
				case "NetStream.Play.Failed":
					DispatchEvent(TVideoEvent.VIDEO_ERROR,TVideoEvent.ecStreamPlayError,'An error has occurred in playback for a reason other than those listed elsewhere in this table, such as the subscriber not having read access.');
					break;
				case "NetStream.Play.FileStructureInvalid":
					DispatchEvent(TVideoEvent.VIDEO_ERROR,TVideoEvent.ecStreamPlayError,'The application detects an invalid file structure and will not try to play this type of file.');
					break;
				case "NetStream.Play.Start":
				case "NetStream.Unpause.Notify":
					DispatchEvent(TVideoEvent.VIDEO_PLAY);
					break;
				case "NetStream.Play.Stop":
					this.OnComplete();
					DispatchEvent(TVideoEvent.VIDEO_STOP);
					break;
				case "NetStream.Seek.InvalidTime":
					_FNetStream.seek(E.info.details);
					break;
			}
		}
		
		private function SecurityErrorHandler(E:SecurityErrorEvent):void{
			DispatchEvent(TVideoEvent.VIDEO_ERROR,TVideoEvent.ecSecurityError,E.text);
		}
		
		public function Play():void{
			if(!DoPlay()) return;
			_FNetStream.resume();
			_FStatus=MediaStatusType.Playing;
			_FPlayFunctionManager.doFunction('OnPlay');
			trace('Video play*****************'+_FT);
		}
		
		public function Pause():void{
			if(_FStatus==MediaStatusType.UnInit) return;
			_FNetStream.pause();
			_FStatus=MediaStatusType.Pasued;
			_FPlayFunctionManager.doFunction('OnPause');
			trace('Video Pause*****************'+_FT);
		}
		
		public function Stop():void{
			if(_FStatus==MediaStatusType.UnInit) return;
			/*_FNetStream.play(false);
			_FNetStream.close();
			_FDoPlayed=false;
			_FVideoControlBar.StopInfo();
			
			*/
			_FNetStream.seek(0);
			this.Pause();
			_FStatus=MediaStatusType.Stoped;
		}
		
		public function Toggle():void{
			if(_FStatus==MediaStatusType.UnInit) return;
			_FNetStream.togglePause();
			if(_FStatus==MediaStatusType.Playing){
				_FStatus=MediaStatusType.Pasued
				_FPlayFunctionManager.doFunction('OnPause');
			}else{
				_FStatus=MediaStatusType.Playing;
				_FPlayFunctionManager.doFunction('OnPlay');
			}
		}
		
		public function get PlayStatus():int{
			return _FStatus;
		}
		
		
		public function Seek(Pos:Number):void{
			_FNetStream.seek(Pos);
		}
		
		public function get CurrentPos():Number{
			return _FNetStream.time;
		}
		public function get Duration():Number{
			return _FVideoDuration;
		}
		
		public function get Volume():Number{
			return _FNetStream.soundTransform.volume;
		}
		
		public function set Volume(value:Number):void{
			var _FSoundTransform:SoundTransform=new SoundTransform(value);
			_FNetStream.soundTransform=_FSoundTransform;
		}
		
		public function set OnPlay(value:Function):void{
			_FPlayFunctionManager.regFunction('OnPlay',value);
		}
		public function set OnPause(value:Function):void{
			_FPlayFunctionManager.regFunction('OnPause',value);
		}
		
		
		private function Paint():void{
			_FVideo.width=VideoPlayerConfig().Width;
			_FVideo.height=VideoPlayerConfig().Height;
			_FPreviewPicture.width=VideoPlayerConfig().Width;
			_FPreviewPicture.height=VideoPlayerConfig().Height;
			_FVideoControlBar.Resize(VideoPlayerConfig().Width);
			_FVideoControlBar.y=this._FVideoContainer.height;
		}
		
		public function set Width(value:Number):void{
			VideoPlayerConfig().Width=value;
			Paint();
		}
		public function get Width():Number{
			return VideoPlayerConfig().Width;
		}
		
		public function set Height(value:Number):void{
			VideoPlayerConfig().Height=value;
			Paint();
		}
		public	function get Height():Number{
			return VideoPlayerConfig().Height;
		}
		
		public function SetDuration(val:Number):void{
			this._FVideoDuration=val;
		}
	}
}